import * as vscode from "vscode";
import { TreeSitter } from "../../../../core/treesitter/TreeSitter";
import { basicTypes } from "../entities/const";

export function getEOL(doc: vscode.TextDocument): string {
  return doc.eol === vscode.EndOfLine.LF ? "\n" : "\r\n";
}

export function filterFunctionSymbols(
  documentSymbols: vscode.DocumentSymbol[]
) {
  return documentSymbols.filter(
    (e) =>
      e.kind === vscode.SymbolKind.Function ||
      e.kind === vscode.SymbolKind.Method
  );
}

export function findAllIndexes<T>(
  array: T[],
  predicate: (value: T, index: number, obj: T[]) => boolean
): number[] {
  const indexes: number[] = [];
  for (let index = 0; index < array.length; index++) {
    if (predicate(array[index], index, array)) {
      indexes.push(index);
    }
  }
  return indexes;
}

/**
 * 获取行的缩进级别
 */
export function getIndentation(line: string): number {
  const match = line.match(/^(\s*)/);
  return match ? match[1].length : 0;
}

/**
 * 匹配类声明
 */
export function matchClassDeclaration(line: string): RegExpMatchArray | null {
  // 匹配 class Name 或 class Name extends Base 格式
  return line.match(
    /^class\s+([A-Za-z_]\w*)\s*(?:extends\s+[A-Za-z_]\w*\s*)?{?/
  );
}

/**
 * 验证是否是有效的类声明（不在注释或字符串中）
 */
export function isValidClassDeclaration(line: string): boolean {
  // 移除行内注释
  line = line.replace(/\/\/.*$/, "");

  // 检查是否在多行注释中
  if (line.includes("/*") || line.includes("*/")) {
    return false;
  }

  // 检查是否在字符串中
  let inString = false;
  let stringChar = "";

  for (let i = 0; i < line.length; i++) {
    const char = line[i];

    if (char === '"' || char === "'") {
      if (!inString) {
        inString = true;
        stringChar = char;
      } else if (char === stringChar) {
        inString = false;
      }
    }

    if (char === "c" && !inString) {
      // 检查是否找到了 'class' 关键字
      if (line.substr(i, 5) === "class") {
        return true;
      }
    }
  }

  return false;
}

export function isBasicType(type: string): boolean {
  const lowerCaseType = type.toLowerCase();
  return Array.from(basicTypes).some(
    (basicType) => basicType.toLowerCase() === lowerCaseType
  );
}

/**
 * 清理类型名称，去除修饰符
 * @param typeName 原始类型名称
 * @returns 清理后的类型名称
 */
export function cleanTypeName(typeName: string): string {
  // 去除const、*、&等修饰
  return typeName
    .replace(/const\s+/g, "")
    .replace(/\*|\&/g, "")
    .replace(/\s+/g, "")
    .split("<")[0] // 去除模板参数
    .trim();
}

/**
 * 转义正则表达式特殊字符
 * @param string 待转义的字符串
 * @returns 转义后的字符串
 */
export function escapeRegExp(string: string): string {
  return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

export function getAccess(text: string) {
  if (text.startsWith("private")) {
    return "private";
  }
  if (text.startsWith("protected")) {
    return "protected";
  }
  return "public";
}

export function removeVirtualKeyword(signature: string): string {
  // 使用正则表达式匹配并去除虚函数关键字
  return signature.replace(/\bvirtual\b\s*/g, "").trim();
}

export function removeAfterEqual(input: string): string {
  const equalIndex = input.indexOf("=");
  if (equalIndex === -1) {
    return input;
  }
  return input.substring(0, equalIndex).trim();
}

// codeMate 分支增强使用
export async function getFirstClassSpecifier(
  text: string,
  language: string
): Promise<string[]> {
  await TreeSitter.getInstance().init();
  return TreeSitter.getInstance().getFirstClassSpecifier(text, language);
}

// 获取文件根路径
export function getRootFilePath(doc: any): string {
  const folders = vscode.workspace.workspaceFolders;
  if (folders && folders.length > 1) {
    const filePath = doc.uri.path;
    let path = "";
    folders.forEach((item: vscode.WorkspaceFolder) => {
      if (filePath.startsWith(item.uri.path)) {
        path = item.uri.path;
      }
    });
    return path;
  } else {
    return folders?.[0].uri.path || "";
  }
}

// 获取测试文件路径 路径不匹配返回""
export function getTestFilePath(filePath: string, rootPath: string): string {
  if (filePath.startsWith("/")) {
    filePath = filePath.slice(1);
  }
  if (rootPath.startsWith("/")) {
    rootPath = rootPath.slice(1);
  }

  // 确保路径分隔符统一为正斜杠
  let normalizedFile = filePath.replace(/\\/g, "/");
  let normalizedRoot = rootPath.replace(/\\/g, "/");

  if (
    normalizedFile
      .substring(0, normalizedFile.indexOf("/"))
      .toLocaleLowerCase() !==
    normalizedRoot.substring(0, normalizedRoot.indexOf("/")).toLocaleLowerCase()
  ) {
    return "";
  }
  // 确保第一个/前的大小写一致,所以直接统一
  const firstPath = normalizedFile
    .substring(0, normalizedFile.indexOf("/"))
    .toLocaleLowerCase();

  normalizedFile = `${firstPath}${normalizedFile.substring(normalizedFile.indexOf("/"))}`;
  normalizedRoot = `${firstPath}${normalizedRoot.substring(normalizedRoot.indexOf("/"))}`;

  if (!normalizedFile.startsWith(normalizedRoot)) {
    return "";
  }

  // 删除根路径后剩下的部分（即文件路径相对于根路径的部分）
  const relativePath = normalizedFile.replace(normalizedRoot, "");

  // 查找是否包含 '/src/'
  const srcIndex = relativePath.lastIndexOf("/src/");
  let testFilePath = "";
  if (srcIndex !== -1) {
    // 替换最后一个 '/src/' 为 '/tests/'
    const beforeSrc = relativePath.substring(0, srcIndex);
    const afterSrc = relativePath.substring(srcIndex + 5); // 5 是 '/src/'.length
    const newRelativePath = `${beforeSrc}${beforeSrc.endsWith("/") ? "tests/" : "/tests/"}${afterSrc}`;
    testFilePath = `${normalizedRoot}${newRelativePath}`;
  } else {
    // 如果不包含 '/src/'，直接在前面加上 '/tests/'
    testFilePath = `${normalizedRoot}/tests${relativePath}`;
  }
  const lastIndexOfPoint = testFilePath.lastIndexOf(".");
  if (lastIndexOfPoint !== -1) {
    const beforePath = testFilePath.substring(0, lastIndexOfPoint);
    const afterPath = testFilePath.substring(lastIndexOfPoint);
    testFilePath = `${beforePath}.test${afterPath}`;
  }

  return testFilePath;
}

export function makeUnique<T>(array: T[], makeID: (element: T) => string): T[] {
  if (!array.length) {
    return array;
  }
  const result: T[] = [];
  const elements = new Set<string>();
  array.forEach((el) => {
    const id = makeID(el);
    const isPresent = elements.has(id);
    elements.add(id);
    if (!isPresent) {
      result.push(el);
    }
  });
  return result;
}

export async function waitForTimeout(
  durationMs: number,
  token?: vscode.CancellationToken
) {
  return new Promise<any>((_, reject) => {
    const startTime = performance.now();
    const intervalId = setInterval(() => {
      const elapsedTime = performance.now() - startTime;
      if (elapsedTime >= durationMs) {
        clearInterval(intervalId);
        reject(
          new TimeoutError(
            `This request was aborted because it took more than ${durationMs} ms`
          )
        );
      }
      if (token && token.isCancellationRequested) {
        clearInterval(intervalId);
        reject(new vscode.CancellationError());
      }
    }, 0);
  });
}

export class TimeoutError extends Error {
  constructor(message: string) {
    super(message);
  }
}

